using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.Concurrent; using System.Threading.Tasks; using System.Threading; namespace ArtificialIntelligence { public class AI { public Job jobSpecification; public List<Job> jobStates = new List<Job>(); public List<Ability> abilities=new List<Ability>(); public Boolean jobIsDone = false; public Action<Job> AssessJobFunction; public Func<List<Job>, List<Job>> Distinct; public int trimmedJobStatePopulation=100; public bool useParallel = true; public int maxWhileLoops = 10; public void Work(Job inJobSpecification, Action<Job> inAssessJobFunction) { AssessJobFunction = inAssessJobFunction; jobSpecification = inJobSpecification; jobStates.Clear(); ConcurrentBag<Job> trimJobStates = new ConcurrentBag<Job>(); ConcurrentBag<Job> gatheredJobStates = new ConcurrentBag<Job>(); jobStates.Add(jobSpecification); int oldJobStateCount; AssessJobFunction(jobStates[0]); int whileCount = 0; int oldJobStateIndex = 0; int L; while (jobIsDone == false) { oldJobStateCount = jobStates.Count; trimJobStates = new ConcurrentBag<Job>(); gatheredJobStates = new ConcurrentBag<Job>(); for (L = 0; L < jobStates.Count; L++) { trimJobStates.Add(jobStates[L]); } Action nest = () => { Job oldJobState; int abilityIndex; Job[] newJobStates; oldJobState = trimJobStates.ElementAt(oldJobStateIndex); if (oldJobState.workedOn == false) { oldJobState.workedOn = true; for (abilityIndex = 0; abilityIndex < abilities.Count; abilityIndex++) { newJobStates = abilities[abilityIndex].WorkFunction(oldJobState).ToArray(); foreach (Job newJobState in newJobStates) { AssessJobFunction(newJobState); newJobState.parent = oldJobState; gatheredJobStates.Add(newJobState); } } } }; int uBound = jobStates.Count; if (useParallel == false) { for (oldJobStateIndex = 0; oldJobStateIndex < uBound; oldJobStateIndex++) { nest(); if (jobIsDone == true) { break; } } } else { ParallelOptions po = new ParallelOptions(); CancellationTokenSource cts = new CancellationTokenSource(); po.CancellationToken = cts.Token; po.MaxDegreeOfParallelism = System.Environment.ProcessorCount; System.Threading.Tasks.Parallel.For(0, uBound, po, (i) => { oldJobStateIndex = i; nest(); if (jobIsDone == true) { uBound = 0; } }); } jobStates = trimJobStates.ToList(); jobStates.AddRange(gatheredJobStates.ToList()); var nonNulls = from n in jobStates where n != null select n; jobStates = nonNulls.ToList(); jobStates = Distinct(jobStates); RankJobStates(); whileCount++; if (jobStates.Count > trimmedJobStatePopulation) { jobStates = jobStates.GetRange(0, trimmedJobStatePopulation); } if (whileCount == maxWhileLoops) { jobIsDone = true; } if (jobStates[0].approved == true) { jobIsDone = true; } //GC.Collect(); } } public void RankJobStates() { jobStates.Sort(RankJobStates); } public static int RankJobStates(Job jobState1, Job jobState2) { if (jobState1.assessment < jobState2.assessment) { return 1; } else if (jobState1.assessment > jobState2.assessment) { return -1; } return 0; } public Job BestJobState { get { return jobStates[0]; } } } }